package org.singledog.permission.utils;

/**
 * 雪花算法生成id
 *
 * @author liuzheming
 * @since 2021.9.18
 */
public class SnowFlake {
	private final static long workerId = 1;
	private final static long sequenceBits = 13L;
	
	private final static long timestampShift = 22L;
	private final static long workerIdShift = 13L;
	private final static long sequenceMask = -1L ^ (-1L << sequenceBits);
	private final static long twepoch = 1500541488162L;
	
	private static long sequence = 0L;
	private static long lastTimestamp = -1L;
	
	public synchronized static long getId() {
		long timestamp = System.currentTimeMillis();
		if (lastTimestamp == timestamp) {
			sequence = (sequence + 1) & sequenceMask;
			if (sequence == 0) {
				timestamp = tillNextMillis(lastTimestamp);
			}
		} else {
			sequence = 0;
		}
		
		lastTimestamp = timestamp;
		long nextId = ((timestamp - twepoch) << timestampShift) | (workerId << workerIdShift) | sequence;
		return nextId;
	}
	
	protected static long tillNextMillis(long lastTimestamp) {
		long timestamp = System.currentTimeMillis();
		while (timestamp <= lastTimestamp) {
			timestamp = System.currentTimeMillis();
		}
		return timestamp;
	}
	
}
